﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using iNet.Tasks;

namespace iNet.Media.Imaging.Filters
{
	/// <summary>
	/// 提供簡單色彩轉換的影像濾鏡工作基底類別。
	/// </summary>
	public abstract class SimpleColorTransformFilterTask : BitmapImageFilterTask
	{
		#region ProgressInfo
		class ProgressInfo
		{
			public readonly double BaseProgress;
			public volatile int NumberOfCompletedRows;
			public readonly int OriginalPixelHeight;
			public readonly double ProgressRange;
			#region 建構子
			public ProgressInfo(int pixelHeight, double baseProgress)
			{
				this.OriginalPixelHeight = pixelHeight;
				this.BaseProgress = baseProgress;
				this.ProgressRange = (100 - baseProgress);
			}
			#endregion
		}
		#endregion
		#region 靜態欄位
		static int[] _DefaultTransformTable8 = new int[256];
		static int[] _DefaultTransformTable16 = new int[65536];
		#endregion
		#region 欄位
		int[] _AlphaTransformTable;
		int[] _BlueColorTransformTable;
		BitmapImageFilterChannels _Channels = BitmapImageFilterChannels.Argb;
		int[] _GreenColorTransformTable;
		int[] _LuminanceTransformTable;
		int[] _RedColorTransformTable;
		#endregion
		#region 型別建構子
		static SimpleColorTransformFilterTask()
		{
			for (int i = _DefaultTransformTable8.Length - 1; i >= 0; --i)
				_DefaultTransformTable8[i] = i;
			for (int i = _DefaultTransformTable16.Length - 1; i >= 0; --i)
				_DefaultTransformTable16[i] = i;
		}
		#endregion
		#region 建構子
		/// <summary>
		/// 初始化新的 SimpleColorTransformFilterTask 執行個體。
		/// </summary>
		protected SimpleColorTransformFilterTask()
		{ }
		/// <summary>
		/// 初始化新的 SimpleColorTransformFilterTask 執行個體。
		/// </summary>
		/// <param name="sourceBitmap">來源點陣圖。</param>
		protected SimpleColorTransformFilterTask(IBitmapImage sourceBitmap)
			: base(sourceBitmap)
		{ }
		#endregion
		#region AlphaTransformTable
		/// <summary>
		/// 取得或設定套用在透明度 (Alpha) 的轉換表，Null (Visual Basic 為 Nothing) 表示透明度不套用轉換。
		/// </summary>
		protected int[] AlphaTransformTable
		{
			get
			{
				return _AlphaTransformTable;
			}
			set
			{
				lock (this.SyncRoot)
				{
					//確認狀態
					switch (this.State)
					{
						case TaskState.Initializing:
						case TaskState.Executing:
						case TaskState.Canceling:
							break;
						default:
							throw new InvalidOperationException();
					}

					//設定參數
					_AlphaTransformTable = value;
				}
			}
		}
		#endregion
		#region ApplyArgbTransform
		unsafe bool ApplyArgbTransform(TaskVersion version, BitmapImageFilterData filterData, BitmapImageFilterChannels channels)
		{
			//確認參數
			if ((channels & BitmapImageFilterChannels.Argb) == 0)
				return true;

			//取得狀態
			int bytesPerPixel = filterData.BytesPerPixel;
			bool is16BitsColor = filterData.Is16BitsColor;
			int pixelWidth = filterData.PixelWidth;
			int pixelHeight = filterData.PixelHeight;
			int stride = filterData.Stride;
			byte* srcPixelBuffer = (byte*)filterData.SourcePixelBuffer;
			byte* resultPixelBuffer = (byte*)filterData.ResultPixelBuffer;
			double baseProgress = (this.Progress ?? 0);
			double progressRange = (100 - baseProgress);

			//取得參數
			int[] alphaTable, redTable, greenTable, blueTable;
			if (!this.ReadValue<int[]>(version, ref _AlphaTransformTable, out alphaTable)
				|| !this.ReadValue<int[]>(version, ref _RedColorTransformTable, out redTable)
				|| !this.ReadValue<int[]>(version, ref _GreenColorTransformTable, out greenTable)
				|| !this.ReadValue<int[]>(version, ref _BlueColorTransformTable, out blueTable)
			)
			{
				return true;
			}

			//初始化轉換表
			if ((channels & BitmapImageFilterChannels.Alpha) == 0 || alphaTable == null)
				alphaTable = (is16BitsColor ? _DefaultTransformTable16 : _DefaultTransformTable8);
			if ((channels & BitmapImageFilterChannels.Red) == 0 || redTable == null)
				redTable = (is16BitsColor ? _DefaultTransformTable16 : _DefaultTransformTable8);
			if ((channels & BitmapImageFilterChannels.Green) == 0 || greenTable == null)
				greenTable = (is16BitsColor ? _DefaultTransformTable16 : _DefaultTransformTable8);
			if ((channels & BitmapImageFilterChannels.Blue) == 0 || blueTable == null)
				blueTable = (is16BitsColor ? _DefaultTransformTable16 : _DefaultTransformTable8);

			//確認轉換表上下限
			alphaTable = this.EnsureTransformRange(alphaTable);
			redTable = this.EnsureTransformRange(redTable);
			greenTable = this.EnsureTransformRange(greenTable);
			blueTable = this.EnsureTransformRange(blueTable);

			//套用色彩轉換
			fixed (int* aTablePtr = alphaTable, rTablePtr = redTable, gTablePtr = greenTable, bTablePtr = blueTable)
			{
				//平行套用
				ProgressInfo progressInfo = new ProgressInfo(pixelHeight, baseProgress);
				int halfHeight = (pixelHeight / 2);
				bool isParallel = (Environment.ProcessorCount > 1 && (pixelWidth * pixelHeight) >= 2000000);
				ManualResetEventSlim barrier = (isParallel ? new ManualResetEventSlim(false) : null);
				if (isParallel)
				{
					int* aTable = aTablePtr;
					int* rTable = rTablePtr;
					int* gTable = gTablePtr;
					int* bTable = bTablePtr;
					byte* srcPixelBuffer2 = (srcPixelBuffer + (stride * halfHeight));
					byte* resultPixelBuffer2 = (resultPixelBuffer + (stride * halfHeight));
					ThreadPool.QueueUserWorkItem((state) =>
					{
						try
						{
							this.ApplyArgbTransform(version, progressInfo, srcPixelBuffer2, resultPixelBuffer2, pixelWidth, (pixelHeight - halfHeight), stride, filterData.PixelFormat, aTable, rTable, gTable, bTable);
						}
						catch (Exception ex)
						{ }
						finally
						{
							barrier.Set();
						}
					});
				}

				//套用轉換
				this.ApplyArgbTransform(version, progressInfo, srcPixelBuffer, resultPixelBuffer, pixelWidth, (isParallel ? halfHeight : pixelHeight), stride, filterData.PixelFormat, aTablePtr, rTablePtr, gTablePtr, bTablePtr);
				if (isParallel)
					barrier.Wait();
			}
			return true;
		}
		unsafe void ApplyArgbTransform(TaskVersion version, ProgressInfo progressInfo, byte* srcPixelBuffer, byte* destPixelBuffer, int width, int height, int stride, PixelFormat pixelFormat, int* aTable, int* rTable, int* gTable, int* bTable)
		{
			if (pixelFormat == PixelFormats.Bgr24)
				this.ApplyArgbTransformFormatBgr24(version, progressInfo, srcPixelBuffer, destPixelBuffer, width, height, stride, rTable, gTable, bTable);
			else if (pixelFormat == PixelFormats.Bgr32)
				this.ApplyArgbTransformFormatBgr32(version, progressInfo, srcPixelBuffer, destPixelBuffer, width, height, stride, rTable, gTable, bTable);
			else if (pixelFormat == PixelFormats.Bgra32)
				this.ApplyArgbTransformFormatBgra32(version, progressInfo, srcPixelBuffer, destPixelBuffer, width, height, stride, aTable, rTable, gTable, bTable);
			else if (pixelFormat == PixelFormats.Rgb48)
				this.ApplyArgbTransformFormatRgb48(version, progressInfo, srcPixelBuffer, destPixelBuffer, width, height, stride, rTable, gTable, bTable);
			else if (pixelFormat == PixelFormats.Rgba64)
				this.ApplyArgbTransformFormatRgba64(version, progressInfo, srcPixelBuffer, destPixelBuffer, width, height, stride, aTable, rTable, gTable, bTable);
			else
				throw new ArgumentException();
		}
		#endregion
		#region ApplyArgbTransformFormatBgr24
		unsafe void ApplyArgbTransformFormatBgr24(TaskVersion version, ProgressInfo progressInfo, byte* srcPixelBuffer, byte* destPixelBuffer, int width, int height, int stride, int* rTable, int* gTable, int* bTable)
		{
			int numOfCompletedRows = 0;
			for (int y = height; y > 0; --y, srcPixelBuffer += stride, destPixelBuffer += stride)
			{
				byte* srcPixel = srcPixelBuffer;
				byte* destPixel = destPixelBuffer;
				for (int x = width; x > 0; --x)
				{
					*(destPixel++) = (byte)bTable[*(srcPixel++)];
					*(destPixel++) = (byte)gTable[*(srcPixel++)];
					*(destPixel++) = (byte)rTable[*(srcPixel++)];
				}
				++numOfCompletedRows;
				if (numOfCompletedRows == 100)
				{
					if (this.IsCanceling)
						return;
					this.ReportProgress(version, progressInfo, numOfCompletedRows);
					numOfCompletedRows = 0;
				}
			}
			this.ReportProgress(version, progressInfo, numOfCompletedRows);
		}
		#endregion
		#region ApplyArgbTransformFormatBgr32
		unsafe void ApplyArgbTransformFormatBgr32(TaskVersion version, ProgressInfo progressInfo, byte* srcPixelBuffer, byte* destPixelBuffer, int width, int height, int stride, int* rTable, int* gTable, int* bTable)
		{
			int numOfCompletedRows = 0;
			for (int y = height; y > 0; --y, srcPixelBuffer += stride, destPixelBuffer += stride)
			{
				byte* srcPixel = srcPixelBuffer;
				byte* destPixel = destPixelBuffer;
				for (int x = width; x > 0; --x, ++srcPixel, ++destPixel)
				{
					*(destPixel++) = (byte)bTable[*(srcPixel++)];
					*(destPixel++) = (byte)gTable[*(srcPixel++)];
					*(destPixel++) = (byte)rTable[*(srcPixel++)];
				}
				++numOfCompletedRows;
				if (numOfCompletedRows == 100)
				{
					if (this.IsCanceling)
						return;
					this.ReportProgress(version, progressInfo, numOfCompletedRows);
					numOfCompletedRows = 0;
				}
			}
			this.ReportProgress(version, progressInfo, numOfCompletedRows);
		}
		#endregion
		#region ApplyArgbTransformFormatBgra32
		unsafe void ApplyArgbTransformFormatBgra32(TaskVersion version, ProgressInfo progressInfo, byte* srcPixelBuffer, byte* destPixelBuffer, int width, int height, int stride, int* aTable, int* rTable, int* gTable, int* bTable)
		{
			int numOfCompletedRows = 0;
			for (int y = height; y > 0; --y, srcPixelBuffer += stride, destPixelBuffer += stride)
			{
				byte* srcPixel = srcPixelBuffer;
				byte* destPixel = destPixelBuffer;
				for (int x = width; x > 0; --x)
				{
					*(destPixel++) = (byte)bTable[*(srcPixel++)];
					*(destPixel++) = (byte)gTable[*(srcPixel++)];
					*(destPixel++) = (byte)rTable[*(srcPixel++)];
					*(destPixel++) = (byte)aTable[*(srcPixel++)];
				}
				++numOfCompletedRows;
				if (numOfCompletedRows == 100)
				{
					if (this.IsCanceling)
						return;
					this.ReportProgress(version, progressInfo, numOfCompletedRows);
					numOfCompletedRows = 0;
				}
			}
			this.ReportProgress(version, progressInfo, numOfCompletedRows);
		}
		#endregion
		#region ApplyArgbTransformFormatRgb48
		unsafe void ApplyArgbTransformFormatRgb48(TaskVersion version, ProgressInfo progressInfo, byte* srcPixelBuffer, byte* destPixelBuffer, int width, int height, int stride, int* rTable, int* gTable, int* bTable)
		{
			int numOfCompletedRows = 0;
			for (int y = height; y > 0; --y, srcPixelBuffer += stride, destPixelBuffer += stride)
			{
				ushort* srcPixel = (ushort*)srcPixelBuffer;
				ushort* destPixel = (ushort*)destPixelBuffer;
				for (int x = width; x > 0; --x)
				{
					*(destPixel++) = (ushort)rTable[*(srcPixel++)];
					*(destPixel++) = (ushort)gTable[*(srcPixel++)];
					*(destPixel++) = (ushort)bTable[*(srcPixel++)];
				}
				++numOfCompletedRows;
				if (numOfCompletedRows == 100)
				{
					if (this.IsCanceling)
						return;
					this.ReportProgress(version, progressInfo, numOfCompletedRows);
					numOfCompletedRows = 0;
				}
			}
			this.ReportProgress(version, progressInfo, numOfCompletedRows);
		}
		#endregion
		#region ApplyArgbTransformFormatRgba64
		unsafe void ApplyArgbTransformFormatRgba64(TaskVersion version, ProgressInfo progressInfo, byte* srcPixelBuffer, byte* destPixelBuffer, int width, int height, int stride, int* aTable, int* rTable, int* gTable, int* bTable)
		{
			int numOfCompletedRows = 0;
			for (int y = height; y > 0; --y, srcPixelBuffer += stride, destPixelBuffer += stride)
			{
				ushort* srcPixel = (ushort*)srcPixelBuffer;
				ushort* destPixel = (ushort*)destPixelBuffer;
				for (int x = width; x > 0; --x)
				{
					*(destPixel++) = (ushort)rTable[*(srcPixel++)];
					*(destPixel++) = (ushort)gTable[*(srcPixel++)];
					*(destPixel++) = (ushort)bTable[*(srcPixel++)];
					*(destPixel++) = (ushort)aTable[*(srcPixel++)];
				}
				++numOfCompletedRows;
				if (numOfCompletedRows == 100)
				{
					if (this.IsCanceling)
						return;
					this.ReportProgress(version, progressInfo, numOfCompletedRows);
					numOfCompletedRows = 0;
				}
			}
			this.ReportProgress(version, progressInfo, numOfCompletedRows);
		}
		#endregion
		#region ApplyFilter
		/// <summary>
		/// 套用濾鏡至點陣圖。
		/// </summary>
		/// <param name="version">目前的工作版本。</param>
		/// <param name="filterData">套用濾鏡所需的資料。</param>
		/// <returns>True 表示濾鏡套用成功，False 表示失敗。</returns>
		protected unsafe override bool ApplyFilter(TaskVersion version, BitmapImageFilterData filterData)
		{
			//取得參數
			BitmapImageFilterChannels channels;
			if (!this.ReadValue<BitmapImageFilterChannels>(version, ref _Channels, out channels))
				return true;

			//套用濾鏡
			if (channels == BitmapImageFilterChannels.Luminance)
			{
				int[] luminanceTable;
				if (!this.ReadValue<int[]>(version, ref _LuminanceTransformTable, out luminanceTable))
					return true;
				if (!this.ApplyLuminanceTramsform(version, filterData, luminanceTable))
					return false;
			}
			else
			{
				if (!this.ApplyArgbTransform(version, filterData, channels))
					return false;
			}

			//完成
			return true;
		}
		#endregion
		#region ApplyLuminanceTramsform
		unsafe bool ApplyLuminanceTramsform(TaskVersion version, BitmapImageFilterData filterData, int[] transformTable)
		{
			//確認參數
			if (transformTable == null)
				return true;

			//確認轉換表上下限
			transformTable = this.EnsureTransformRange(transformTable);

			//取得狀態
			int bytesPerPixel = filterData.BytesPerPixel;
			int pixelWidth = filterData.PixelWidth;
			int pixelHeight = filterData.PixelHeight;
			int stride = filterData.Stride;
			byte* srcPixelBuffer = (byte*)filterData.SourcePixelBuffer;
			byte* resultPixelBuffer = (byte*)filterData.ResultPixelBuffer;
			double baseProgress = (this.Progress ?? 0);
			double progressRange = (100 - baseProgress);

			//套用亮度轉換
			fixed (int* lTablePtr = LuminanceTransformTable)
			{
				//平行套用
				int halfHeight = (pixelHeight / 2);
				ProgressInfo progressInfo = new ProgressInfo(pixelHeight, baseProgress);
				bool isParallel = (Environment.ProcessorCount > 1 && (pixelWidth * pixelHeight) >= 2000000);
				ManualResetEventSlim barrier = (isParallel ? new ManualResetEventSlim(false) : null);
				if (isParallel)
				{
					int* lTable = lTablePtr;
					byte* srcPixelBuffer2 = (srcPixelBuffer + (stride * halfHeight));
					byte* resultPixelBuffer2 = (resultPixelBuffer + (stride * halfHeight));
					try
					{
						this.ApplyLuminanceTramsform(version, progressInfo, srcPixelBuffer2, resultPixelBuffer2, pixelWidth, (pixelHeight - halfHeight), stride, filterData.PixelFormat, lTable);
					}
					catch (Exception ex)
					{ }
					finally
					{
						barrier.Set();
					}
				}

				//套用轉換
				this.ApplyLuminanceTramsform(version, progressInfo, srcPixelBuffer, resultPixelBuffer, pixelWidth, (isParallel ? halfHeight : pixelHeight), stride, filterData.PixelFormat, lTablePtr);
				if (isParallel)
					barrier.Wait();
			}
			return true;
		}
		unsafe void ApplyLuminanceTramsform(TaskVersion version, ProgressInfo progressInfo, byte* srcPixelBuffer, byte* destPixelBuffer, int width, int height, int stride, PixelFormat pixelFormat, int* lTable)
		{
			if (pixelFormat == PixelFormats.Bgr24)
				this.ApplyLuminanceTransformFormatBgr24(version, progressInfo, srcPixelBuffer, destPixelBuffer, width, height, stride, lTable);
			else if (pixelFormat == PixelFormats.Bgr32 || pixelFormat == PixelFormats.Bgra32)
				this.ApplyLuminanceTransformFormatBgr32(version, progressInfo, srcPixelBuffer, destPixelBuffer, width, height, stride, lTable);
			else if (pixelFormat == PixelFormats.Rgb48)
				this.ApplyLuminanceTransformFormatRgb48(version, progressInfo, srcPixelBuffer, destPixelBuffer, width, height, stride, lTable);
			else if (pixelFormat == PixelFormats.Rgba64)
				this.ApplyLuminanceTransformFormatRgba64(version, progressInfo, srcPixelBuffer, destPixelBuffer, width, height, stride, lTable);
			else
				throw new ArgumentException();
		}
		#endregion
		#region ApplyLuminanceTransformFormatBgr24
		unsafe void ApplyLuminanceTransformFormatBgr24(TaskVersion version, ProgressInfo progressInfo, byte* srcPixelBuffer, byte* destPixelBuffer, int width, int height, int stride, int* lTable)
		{
			int numOfCompletedRows = 0;
			for (int y = height; y > 0; --y, srcPixelBuffer += stride, destPixelBuffer += stride)
			{
				byte* srcPixel = srcPixelBuffer;
				byte* destPixel = destPixelBuffer;
				for (int x = width; x > 0; --x)
				{
					int r = *(srcPixel++);
					int g = *(srcPixel++);
					int b = *(srcPixel++);
					int luma = ColorConversion.ToLuminanceUnsafe(r, g, b);
					double ratio = ((double)lTable[luma] / luma);
					r = (int)(r * ratio);
					g = (int)(g * ratio);
					b = (int)(b * ratio);
					if (r > 255)
						r = 255;
					if (g > 255)
						g = 255;
					if (b > 255)
						b = 255;
					*(destPixel++) = (byte)r;
					*(destPixel++) = (byte)g;
					*(destPixel++) = (byte)b;
				}
				++numOfCompletedRows;
				if (numOfCompletedRows == 300)
				{
					if (this.IsCanceling)
						return;
					this.ReportProgress(version, progressInfo, numOfCompletedRows);
					numOfCompletedRows = 0;
				}
			}
			this.ReportProgress(version, progressInfo, numOfCompletedRows);
		}
		#endregion
		#region ApplyLuminanceTransformFormatBgr32
		unsafe void ApplyLuminanceTransformFormatBgr32(TaskVersion version, ProgressInfo progressInfo, byte* srcPixelBuffer, byte* destPixelBuffer, int width, int height, int stride, int* lTable)
		{
			int numOfCompletedRows = 0;
			for (int y = height; y > 0; --y, srcPixelBuffer += stride, destPixelBuffer += stride)
			{
				byte* srcPixel = srcPixelBuffer;
				byte* destPixel = destPixelBuffer;
				for (int x = width; x > 0; --x, ++srcPixel, ++destPixel)
				{
					int r = *(srcPixel++);
					int g = *(srcPixel++);
					int b = *(srcPixel++);
					int luma = ColorConversion.ToLuminanceUnsafe(r, g, b);
					double ratio = ((double)lTable[luma] / luma);
					r = (int)(r * ratio);
					g = (int)(g * ratio);
					b = (int)(b * ratio);
					if (r > 255)
						r = 255;
					if (g > 255)
						g = 255;
					if (b > 255)
						b = 255;
					*(destPixel++) = (byte)r;
					*(destPixel++) = (byte)g;
					*(destPixel++) = (byte)b;
				}
				++numOfCompletedRows;
				if (numOfCompletedRows == 300)
				{
					if (this.IsCanceling)
						return;
					this.ReportProgress(version, progressInfo, numOfCompletedRows);
					numOfCompletedRows = 0;
				}
			}
			this.ReportProgress(version, progressInfo, numOfCompletedRows);
		}
		#endregion
		#region ApplyLuminanceTransformFormatRgb48
		unsafe void ApplyLuminanceTransformFormatRgb48(TaskVersion version, ProgressInfo progressInfo, byte* srcPixelBuffer, byte* destPixelBuffer, int width, int height, int stride, int* lTable)
		{
			int numOfCompletedRows = 0;
			for (int y = height; y > 0; --y, srcPixelBuffer += stride, destPixelBuffer += stride)
			{
				ushort* srcPixel = (ushort*)srcPixelBuffer;
				ushort* destPixel = (ushort*)destPixelBuffer;
				for (int x = width; x > 0; --x)
				{
					int r = *(srcPixel++);
					int g = *(srcPixel++);
					int b = *(srcPixel++);
					int luma = ColorConversion.ToLuminanceUnsafe(r, g, b);
					double ratio = ((double)lTable[luma] / luma);
					r = (int)(r * ratio);
					g = (int)(g * ratio);
					b = (int)(b * ratio);
					if (r > 65535)
						r = 65535;
					if (g > 65535)
						g = 65535;
					if (b > 65535)
						b = 65535;
					*(destPixel++) = (ushort)r;
					*(destPixel++) = (ushort)g;
					*(destPixel++) = (ushort)b;
				}
				++numOfCompletedRows;
				if (numOfCompletedRows == 300)
				{
					if (this.IsCanceling)
						return;
					this.ReportProgress(version, progressInfo, numOfCompletedRows);
					numOfCompletedRows = 0;
				}
			}
			this.ReportProgress(version, progressInfo, numOfCompletedRows);
		}
		#endregion
		#region ApplyLuminanceTransformFormatRgba64
		unsafe void ApplyLuminanceTransformFormatRgba64(TaskVersion version, ProgressInfo progressInfo, byte* srcPixelBuffer, byte* destPixelBuffer, int width, int height, int stride, int* lTable)
		{
			int numOfCompletedRows = 0;
			for (int y = height; y > 0; --y, srcPixelBuffer += stride, destPixelBuffer += stride)
			{
				ushort* srcPixel = (ushort*)srcPixelBuffer;
				ushort* destPixel = (ushort*)destPixelBuffer;
				for (int x = width; x > 0; --x, ++srcPixel, ++destPixel)
				{
					int r = *(srcPixel++);
					int g = *(srcPixel++);
					int b = *(srcPixel++);
					int luma = ColorConversion.ToLuminanceUnsafe(r, g, b);
					double ratio = ((double)lTable[luma] / luma);
					r = (int)(r * ratio);
					g = (int)(g * ratio);
					b = (int)(b * ratio);
					if (r > 65535)
						r = 65535;
					if (g > 65535)
						g = 65535;
					if (b > 65535)
						b = 65535;
					*(destPixel++) = (ushort)r;
					*(destPixel++) = (ushort)g;
					*(destPixel++) = (ushort)b;
				}
				++numOfCompletedRows;
				if (numOfCompletedRows == 300)
				{
					if (this.IsCanceling)
						return;
					this.ReportProgress(version, progressInfo, numOfCompletedRows);
					numOfCompletedRows = 0;
				}
			}
			this.ReportProgress(version, progressInfo, numOfCompletedRows);
		}
		#endregion
		#region Channels
		/// <summary>
		/// 取得或設定套用濾鏡的色彩組合，預設值為 BitmapImageFilterChannels.Argb。
		/// </summary>
		public virtual BitmapImageFilterChannels Channels
		{
			get
			{
				return _Channels;
			}
			set
			{
				this.SetInitializingParameter<BitmapImageFilterChannels>(ref _Channels, value);
			}
		}
		#endregion
		#region EnsureTransformRange
		int[] EnsureTransformRange(int[] table)
		{
			bool isCloneTable = false;
			int maxColor = (table.Length - 1);
			for (int i = maxColor; i >= 0; --i)
			{
				int color = table[i];
				if (color < 0)
				{
					if (!isCloneTable)
					{
						table = (table.Clone() as int[]);
						isCloneTable = true;
					}
					table[i] = 0;
				}
				else if (color > maxColor)
				{
					if (!isCloneTable)
					{
						table = (table.Clone() as int[]);
						isCloneTable = true;
					}
					table[i] = maxColor;
				}
			}
			return table;
		}
		#endregion
		#region BlueColorTransformTable
		/// <summary>
		/// 取得或設定套用在藍色的色彩轉換表，Null (Visual Basic 為 Nothing) 表示藍色不套用轉換。
		/// </summary>
		protected int[] BlueColorTransformTable
		{
			get
			{
				return _BlueColorTransformTable;
			}
			set
			{
				lock (this.SyncRoot)
				{
					//確認狀態
					switch (this.State)
					{
						case TaskState.Initializing:
						case TaskState.Executing:
						case TaskState.Canceling:
							break;
						default:
							throw new InvalidOperationException();
					}

					//設定參數
					_BlueColorTransformTable = value;
				}
			}
		}
		#endregion
		#region GreenColorTransformTable
		/// <summary>
		/// 取得或設定套用在綠色的色彩轉換表，Null (Visual Basic 為 Nothing) 表示綠色不套用轉換。
		/// </summary>
		protected int[] GreenColorTransformTable
		{
			get
			{
				return _GreenColorTransformTable;
			}
			set
			{
				lock (this.SyncRoot)
				{
					//確認狀態
					switch (this.State)
					{
						case TaskState.Initializing:
						case TaskState.Executing:
						case TaskState.Canceling:
							break;
						default:
							throw new InvalidOperationException();
					}

					//設定參數
					_GreenColorTransformTable = value;
				}
			}
		}
		#endregion
		#region LuminanceTransformTable
		/// <summary>
		/// 取得或設定套用在光線強度的轉換表，Null (Visual Basic 為 Nothing) 表示光線強度不套用轉換。
		/// </summary>
		protected int[] LuminanceTransformTable
		{
			get
			{
				return _LuminanceTransformTable;
			}
			set
			{
				lock (this.SyncRoot)
				{
					//確認狀態
					switch (this.State)
					{
						case TaskState.Initializing:
						case TaskState.Executing:
						case TaskState.Canceling:
							break;
						default:
							throw new InvalidOperationException();
					}

					//設定參數
					_LuminanceTransformTable = value;
				}
			}
		}
		#endregion
		#region RedColorTransformTable
		/// <summary>
		/// 取得或設定套用在紅色的色彩轉換表，Null (Visual Basic 為 Nothing) 表示紅色不套用轉換。
		/// </summary>
		protected int[] RedColorTransformTable
		{
			get
			{
				return _RedColorTransformTable;
			}
			set
			{
				lock (this.SyncRoot)
				{
					//確認狀態
					switch (this.State)
					{
						case TaskState.Initializing:
						case TaskState.Executing:
						case TaskState.Canceling:
							break;
						default:
							throw new InvalidOperationException();
					}

					//設定參數
					_RedColorTransformTable = value;
				}
			}
		}
		#endregion
		#region ReportProgress
		void ReportProgress(TaskVersion version, ProgressInfo progressInfo, int numOfCompletedRows)
		{
			if (numOfCompletedRows <= 0)
				return;
			lock (progressInfo)
			{
				progressInfo.NumberOfCompletedRows += numOfCompletedRows;
				this.ReportProgress(version, progressInfo.BaseProgress + (progressInfo.NumberOfCompletedRows * progressInfo.ProgressRange / progressInfo.OriginalPixelHeight));
			}
		}
		#endregion
		#region ValidateInitParameters
		/// <summary>
		/// 驗證初始化參數是否正確。
		/// </summary>
		/// <returns>True 表示參數正確，False 表示不正確。</returns>
		protected override bool ValidateInitParameters()
		{
			return (base.ValidateInitParameters()
				&& ((_Channels & BitmapImageFilterChannels.Luminance) == 0 || _Channels == BitmapImageFilterChannels.Luminance));
		}
		#endregion
	}
}
